#include "../../ExEngine/math/matrix.h"

#include "../../ExEngine/physics/actor.h"
#include "../../ExEngine/physics/physics.h"
#include "../../ExEngine/math/quaternion.h"
#include "../../ExEngine/common/util.h"
#include "../../ExEngine/engine/engine.h"
#include "../../ExEngine/engine/object.h"
#include "../../ExEngine/engine/camera.h"
#include "../../ExEngine/render/d3d_mesh.h"
#include "../../ExEngine/render/d3d.h"
#include "../../ExEngine/sound/dsound.h"
#include "../../ExEngine/input/dinput.h"

#include "ent_cameratoggle.h"
#include "player.h"
#include "../game/core.h"

const float DURATION = 1.7525f;
const float MUZZLE = 0.005f;
const float OFFSHOOT = 0.5f;

/**********************************************************************
 *
 **********************************************************************/

CCameraToggle::CCameraToggle() : CObject()
{
	m_transitionTimer.Set(1.5f);
	m_isValid = true;
}

HRESULT CCameraToggle::Create()
{	 
	if(FAILED(CEngine::GetInstance()->GetPhysics()->CreateFieldActor("camera_toggle.HKX", &m_pPhysics, m_transform, this)))
	{
		Release();
		return E_FAIL;
	}

	m_pPhysics->SetCollisionCallback(Game::g_Player);

	return S_OK;
}

HRESULT CCameraToggle::Release()
{	
	HRESULT result = S_OK; 
	if(m_pPhysics)
	{
		CPhysics* pPhysics = CEngine::GetInstance()->GetPhysics();
		if(FAILED(pPhysics->ReleaseActor(m_pPhysics)))
			result = E_FAIL;
		m_pPhysics = NULL;
	}
	return result;
}

void CCameraToggle::Idle()
{
}

void CCameraToggle::setPosition(const Vector3f &position)
{
	m_transform = Matrix4f::identity();
	m_transform.SetTranslation(position); 
	if(m_pPhysics)
		m_pPhysics->SetTransform(m_transform);
	
}

void CCameraToggle::OnCollisionEvent(const Vector3f& contactPoint, const Vector3f& contactNormal, CObject* pOtherObject) {

	if(pOtherObject == Game::g_Player)
	{
		//If the last transition was interupted, reset the timer
		if(m_transitionTimer.IsActive())
			m_transitionTimer.Reset();

		m_transitionTimer.Start();

		if(Vector3f::dot(&m_transform.Right(), &Game::g_Player->getPosition()) - Vector3f::dot(&m_transform.Right(), &m_transform.Translation()) < 0)
		{
			m_postTransitionState = Game::CHASE;
			Game::g_GamePlayMode = Game::TRANSITION;
			Game::g_Player->SetDirectionDriver(m_transform.Right());
		//	Game::g_TransitionCameraAnchor = 
		//		(m_transform.Translation() + Game::g_Player->GetTransform().Foward() * 4.0f + Game::g_Player->GetTransform().Up() * 2.0f);
		}
		else
		{
			//Ease play direction towards plane nromal (m_transform.Right())
			//maintain player speed as from begning transtion
			m_postTransitionState = Game::SIDE_SCROLL;
			Game::g_GamePlayMode = Game::TRANSITION;
			Game::g_Player->SetDirectionDriver(m_transform.Left());
		//	Game::g_TransitionCameraAnchor = (m_transform.Left() * 5 + m_transform.Translation()) + Vector3f(0.0f, 2.0f, -4.0f);
		}
	}
}

bool CCameraToggle::isValid() {
	return m_isValid;
}

void CCameraToggle::Update(const float dt)
{	
	if(m_transitionTimer.IsComplete()) {
		m_transitionTimer.Reset();
		Game::g_Player->SetHumanDriver();
		Game::g_GamePlayMode = m_postTransitionState;
	}
	else if(m_transitionTimer.IsActive()) {
		m_transitionTimer.Update(dt);
		Game::g_TransitionCameraTarget = Game::g_Player->getPosition();

		if(m_postTransitionState == Game::CHASE)
			Game::g_TransitionCameraAnchor = 
			(Game::g_Player->GetTransform().Translation() + Game::g_Player->GetTransform().Foward() * 2.0f + Game::g_Player->GetTransform().Up() * 1.0f);
		else if(m_postTransitionState == Game::SIDE_SCROLL)
			Game::g_TransitionCameraAnchor = 
			(Game::g_Player->GetTransform().Translation() + m_transform.Left() * 5  + Vector3f(0.0f, 2.0f, -4.0f));
	}
}

void CCameraToggle::Draw()
{	
	//CEngine::GetInstance()->GetRenderer()->DrawLine(m_transform.Translation() + Vector3f(0,2,0),Vector3f(0,2,0)+m_transform.Translation() + m_transform.Right() * 10);
	GetRenderer()->DrawSphere(m_transform.Translation());
	GetRenderer()->DrawPoint(m_transform.Translation() + m_transform.Left() * 5);
	GetRenderer()->DrawPoint(m_transform.Translation() + m_transform.Left() * -5, 2, Color3f(0.0f,1.0f,0.0f));
}